Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reform internal use of template compiler #20587

Merged
merged 1 commit into from
Dec 11, 2023
Merged

Conversation

ef4
Copy link
Contributor

@ef4 ef4 commented Dec 1, 2023

Previously, ember-source had a weird custom way of compiling templates that appear within its own source. This PR makes it work the same way we do everywhere else, using babel-plugin-ember-template-compilation.

This required solving a boostrapping problem: the babel plugin needs ember-template-compiler.js, our build produces
ember-template-compiler.js, but our build wants to use the babel plugin. I solved it by making the template compiler directly evaluatable in node, with no build at all.

The full legacy ember-template-compiler API has a lot of silly things shoved into it (like a reexport of all of the Ember metapackage), and that was inextricably circular, so I introduced ember-template-compiler/minimal for this internal use case.

@@ -54,32 +53,21 @@ module.exports.qunit = function _qunit() {

module.exports.getPackagesES = function getPackagesES() {
let input = new Funnel(`packages`, {
exclude: ['loader/**', 'external-helpers/**'],
exclude: ['loader/**', 'external-helpers/**', '**/node_modules'],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR makes all the packages real pnpm workspaces, which was necessary to make the ember-template-compiler package actually evaluatable in node. Previously not all packages were. This extra filtering is necessary now that pnpm is creating node_modules directories inside the packages.

],
{
// we're replacing the ember/verion file with the actual version number
overwrite: true,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The template compiler imports the version. Previously that would die because the version file is dynamically created. Now we have a placeholder file on disk that gets replaced in the build, so that our internal usage of template compiler doesn't die.

compilerPath = path.resolve(__dirname, '../broccoli/glimmer-template-compiler');
} else {
// When we're building an app, we use the already built template compiler.
compilerPath = path.resolve(__dirname, '../dist/ember-template-compiler.js');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This keeps the exact old behavior when building apps, and only changes the behavior when ember is building itself.

@@ -111,6 +111,8 @@
"@embroider/shared-internals": "^2.5.0",
"@rollup/plugin-babel": "^6.0.3",
"@simple-dom/document": "^1.4.0",
"@swc/core": "^1.3.100",
"@swc-node/register": "^1.6.8",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how we can directly evaluate the template compiler without a build.

import { precompileTemplate } from '@ember/template-compilation';
export default precompileTemplate('', {
moduleName: 'packages/@ember/-internals/glimmer/lib/templates/empty.hbs',
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to drop all special support for hbs files, and several hacks around their types, by making them just be the equivalent javascript.

@@ -0,0 +1,2 @@
// this file gets replaced with the real value during the build
export default 'VERSION_GOES_HERE';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By having a real file on disk, we get to eliminate hacks around the types and we avoid crashing if you try to directly evaluate in node, without a build.

packages:
- 'packages/*'
- 'packages/@ember/*'
- 'packages/@glimmer/*'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I converted this repo to pnpm, it looks like pnpm was auto-detecting all our packages. But it turns out it was not detecting all of them. This makes it explicit.

@@ -0,0 +1,2 @@
# this tells pnpm we are a separate project with a separate install, not part of
# the monorepo's workspaces.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding pnpm-workspace.yaml at the root required also adding this, in order to keep the old behavior where this subdir gets an entirely independent pnpm install.

Arguably it would be better to just make this subdir another workspace, but that turns out to be non-trivial given NPM dependency hell, so I didn't try to attempt that change in this PR.

'@ember/-internals/glimmer/lib/templates/outlet.d.ts',
'@ember/-internals/glimmer/lib/templates/root.d.ts',
'@ember/-internals/glimmer/lib/templates/textarea.d.ts',
];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this was helping typescript deal with fake files that don't exist. But now all of them are real files.

@ef4 ef4 force-pushed the direct-eval-template-compiler branch from c3afc77 to 2efb6a9 Compare December 1, 2023 19:02
@@ -1,2 +0,0 @@
declare const VERSION: string;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type was actually a lie. The generated version module only contains a default export. So this PR is also a bugfix to the types.

Base automatically changed from internal-coordination to main December 1, 2023 19:08
@ef4 ef4 force-pushed the direct-eval-template-compiler branch from 2efb6a9 to 46c0784 Compare December 1, 2023 20:04
@ef4
Copy link
Contributor Author

ef4 commented Dec 1, 2023

Oh wow, GitHub automatically changed the base branch after merging the other one, nice.

Previously, ember-source had a weird custom way of compiling templates
that appear within its own source. This PR makes it work the same way we
do everywhere else, using babele-plugin-ember-template-compilation.

This required solving a boostrapping problem: the babel plugin needs
ember-template-compiler.js, our build produces
ember-template-compiler.js, but our build wants to use the babel plugin.
I solved it by making the template compiler directly evaluatable in
node, with no build at all.

The *full* legacy ember-template-compiler API has a lot of silly things
shoved into it (like a reexport of all of the `Ember` metapackage), and
that was inextricably circular, so I introduced
`ember-template-compiler/minimal` for this internal use case.
@ef4 ef4 force-pushed the direct-eval-template-compiler branch from 3b99f94 to b4ab87b Compare December 2, 2023 21:02
@ef4 ef4 marked this pull request as ready for review December 2, 2023 21:04
Copy link
Sponsor Contributor

@NullVoxPopuli NullVoxPopuli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super excited for this! thanks for the self review, that was super helpful!

@ef4 ef4 merged commit 82a1b20 into main Dec 11, 2023
18 checks passed
@ef4 ef4 deleted the direct-eval-template-compiler branch December 11, 2023 12:42
ef4 added a commit that referenced this pull request Dec 12, 2023
As of #20587, the modules published under `dist/packages` act more like normal addon code,  in that their templates are published as calls to `precompileTemplate` rather than wire format.

But that makes this the first time that Embroider is seeing these templates, and because they are in loose mode and use the dynamic component helper they are un-analyzable.

This PR:
 - switches them to strict mode
 - fixes the declared types for `precompileTemplate`, which were a lie before. `scope` is allowed in non-strict mode. `scope` is optional even in strict mode.
 - fixes a spelling error in a recently-introduced internal method, because I noticed it and it annoyed me.
ef4 added a commit that referenced this pull request Dec 15, 2023
…ncies

This is a bugfix to #20587.

We need to have an explicit dependency (not devDependency) on babel-plugin-ember-template-compilation because it's used from our addon main, which runs inside apps builds.
kategengler pushed a commit that referenced this pull request Dec 20, 2023
As of #20587, the modules published under `dist/packages` act more like normal addon code,  in that their templates are published as calls to `precompileTemplate` rather than wire format.

But that makes this the first time that Embroider is seeing these templates, and because they are in loose mode and use the dynamic component helper they are un-analyzable.

This PR:
 - switches them to strict mode
 - fixes the declared types for `precompileTemplate`, which were a lie before. `scope` is allowed in non-strict mode. `scope` is optional even in strict mode.
 - fixes a spelling error in a recently-introduced internal method, because I noticed it and it annoyed me.

(cherry picked from commit 82b5b1d)
kategengler pushed a commit that referenced this pull request Dec 20, 2023
…ncies

This is a bugfix to #20587.

We need to have an explicit dependency (not devDependency) on babel-plugin-ember-template-compilation because it's used from our addon main, which runs inside apps builds.

(cherry picked from commit 6d33841)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants